﻿////////////////////////////////////////////////////////////////////////////////////////////////////
// <copyright file="GameComparer.cs" company="SingularityShift.com">
// Copyright (c) 2010 SingularityShift.com. All rights reserved.
// </copyright>
// <author>Ben McClure</author>
// <email>ben@singularityshift.com</email>
// <date>11/24/2010</date>
// <summary>Implements the game comparer class</summary>
////////////////////////////////////////////////////////////////////////////////////////////////////
namespace GameLib.Games.Components
{
    using System;
    using System.Collections.Generic;
    using System.IO;

    /// <summary>
    /// An indicator of what type of comparison to perform on a ModFile
    /// </summary>
    public enum GameComparisonType
    {
        Id,

        Title,

        Exe,

        TimeAccessed,
    }

    public class GameComparer<T> : IComparer<T> where T : IGame
    {
        public GameComparer(GameComparisonType comparisonType)
        {
            this.ComparisonType = comparisonType;
            this.Reverse = false;
        }

        public GameComparer(GameComparisonType comparisonType, bool reverse)
        {
            this.ComparisonType = comparisonType;
            this.Reverse = reverse;
        }

        public GameComparer(GameComparisonType comparisonType, string dir, bool reverse)
        {
            this.ComparisonType = comparisonType;
            this.Dir = dir;
            this.Reverse = reverse;
        }

        /// <summary>
        /// Gets or sets the type of comparison to perform
        /// </summary>
        public GameComparisonType ComparisonType
        {
            get;
            protected set;
        }

        /// <summary>
        /// Gets or sets a value indicating whether to compare in reverse
        /// </summary>
        public bool Reverse
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the directory the games should be located in (otherwise whatever location is specified in each mod is used)
        /// </summary>
        public string Dir
        {
            get;
            set;
        }

        /// <summary>
        /// Compares two IMods by their last modification times
        /// </summary>
        /// <param name="x">The first IMod to compare</param>
        /// <param name="y">The second IMod to compare</param>
        /// <returns>An integer representing the order of the mods as defined by the comparison</returns>
        public int Compare(T x, T y)
        {
            string path1;
            string path2;
            if ((this.Dir.Length > 0) && Directory.Exists(this.Dir))
            {
                path1 = this.Dir + "\\" + Path.GetFileName(x.Exe);
                path2 = this.Dir + "\\" + Path.GetFileName(y.Exe);
            }
            else
            {
                path1 = x.GameDir;
                path2 = y.GameDir;
                if (x.BinDir.Length > 0)
                {
                    path1 = path1 + "\\" + x.BinDir;
                }
                if (y.BinDir.Length > 0)
                {
                    path2 = path2 + "\\" + y.BinDir;
                }
                path1 = path1 + "\\" + x.Exe;
                path2 = path2 + "\\" + y.Exe;
            }

            int result = 0;
            switch (this.ComparisonType)
            {
                case GameComparisonType.Id:
                    result = string.Compare(x.Id, y.Id, StringComparison.CurrentCultureIgnoreCase);
                    break;
                case GameComparisonType.Title:
                    result = string.Compare(x.Title, y.Title, StringComparison.CurrentCultureIgnoreCase);
                    break;
                case GameComparisonType.Exe:
                    result = string.Compare(x.Exe, y.Exe, StringComparison.CurrentCultureIgnoreCase);
                    break;
                case GameComparisonType.TimeAccessed:
                    result = File.GetLastAccessTime(path1).CompareTo(File.GetLastAccessTime(path2));
                    break;
            }

            return this.Reverse ? -result : result;
        }
    }
}